home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / FFIND.PAK / FFIND.C next >
C/C++ Source or Header  |  1997-05-06  |  33KB  |  1,012 lines

  1. // Borland C++ - (C) Copyright 1991, 1995 by Borland International
  2.  
  3. //*******************************************************************
  4. //
  5. // program - Ffind.c
  6. // purpose - a Windows program to find files on system drives.
  7. //
  8. //*******************************************************************
  9.  
  10. #define  STRICT
  11. #include <windows.h>
  12. #pragma hdrstop
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <time.h>
  17. #include <ctype.h>
  18. #include <io.h>
  19. #include <dos.h>
  20. #include <dir.h>
  21. #include <windowsx.h>
  22.  
  23. #include "ffind.h"
  24.  
  25. #define MAX_QRT_LEN 100
  26.  
  27. #ifndef __FLAT__          // 16-bit applications are limited to the old
  28. #define MAX_PATH MAXPATH  // path length limit of 80
  29. #endif
  30.  
  31. // data initialized by first instance
  32. typedef struct tagSETUPDATA
  33.   {
  34.     char   szAppName[10]; // name of application
  35.   } SETUPDATA;
  36.  
  37. SETUPDATA SetUpData;
  38.  
  39. char buf[256];
  40.  
  41. // Data that can be referenced throughout the
  42. // program but not passed to other instances
  43.  
  44. HINSTANCE hInst;                              // hInstance of application
  45. HWND      hWndMain;                           // hWnd of main window
  46.  
  47. char      qrtxt[MAX_QRT_LEN];                 // dialog input string
  48.  
  49. char      file_name_pattern[MAX_QRT_LEN];     // file name search pattern
  50. long      file_count;                         // count of files found
  51.  
  52. int       xChar, yChar, yCharnl;              // character size
  53. int       xClient, yClient;                   // client window size
  54.  
  55. LOGFONT   cursfont;                           // font structure
  56. HFONT     holdsfont;                          // handle of original font
  57. HFONT     hnewsfont;                          // handle of new fixed font
  58.  
  59. HGLOBAL   hdlgr;                              // handle of dialog resource
  60.  
  61. int       ndrives;                            // number of drives in system
  62. char      fdrives[10];                        // letters of floppy drives
  63. char      hdrives[30];                        // letters of hard drives
  64.  
  65. FARPROC   lpModelessProc;                     // pointer to proc for modeless box
  66. HWND      hQryDlgBox;                         // handle of modeless dialog box
  67.  
  68. // function prototypes
  69.  
  70. int      PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  71.                         LPSTR lpszCmdLine, int cmdShow);
  72.  
  73. void            InitFfind(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  74.                           LPSTR lpszCmdLine, int cmdShow);
  75. void            InitFfindFirst(HINSTANCE hInstance);
  76. void            InitFfindAdded(HINSTANCE hPrevInstance);
  77. void            InitFfindEvery(HINSTANCE hInstance, int cmdShow);
  78. void            CloseFfind(void);
  79.  
  80. LRESULT CALLBACK _export  FfindWndProc(HWND hWnd, UINT message,
  81.                                 WPARAM wParam, LPARAM lParam);
  82.  
  83. void            InitMainDlg(HWND hWnd);
  84. BOOL CALLBACK   _export MainDlgBoxProc(HWND hDlg, UINT message,
  85.                            WPARAM wParam, LPARAM lParam);
  86.  
  87. long            FindFile(char *drives, char *pattern);
  88. int             DoADir(char *patternp, char *patternn, char *include);
  89. int             FnMatch(char *pat, char *name);
  90. void            FindDrives(char *fdrives, char *hdrives);
  91. char           *FmtEntry(char *buf, char *name, char *patternp,
  92.                          unsigned time, unsigned date, long size);
  93.  
  94. //*******************************************************************
  95. // WinMain - ffind main
  96. //
  97. // paramaters:
  98. //             hInstance     - The instance of this instance of this
  99. //                             application.
  100. //             hPrevInstance - The instance of the previous instance
  101. //                             of this application. This will be 0
  102. //                             if this is the first instance.
  103. //             lpszCmdLine   - A long pointer to the command line that
  104. //                             started this application.
  105. //             cmdShow       - Indicates how the window is to be shown
  106. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  107. //                             SW_MIMIMIZE.
  108. //
  109. // returns:
  110. //             wParam from last message.
  111. //
  112. //*******************************************************************
  113. int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  114.                    LPSTR lpszCmdLine, int cmdShow)
  115. {
  116.     MSG   msg;
  117.  
  118.     // Go init this application.
  119.     InitFfind(hInstance, hPrevInstance, lpszCmdLine, cmdShow);
  120.  
  121.     // Get and dispatch messages for this applicaton.
  122.     while (GetMessage(&msg, NULL, 0, 0))
  123.     {
  124.       if(!hQryDlgBox || !IsWindow(hQryDlgBox) ||
  125.          !IsDialogMessage( hQryDlgBox, &msg))
  126.       {
  127.         TranslateMessage(&msg);
  128.         DispatchMessage(&msg);
  129.       }
  130.     }
  131.  
  132.     return(msg.wParam);
  133. }
  134.  
  135. //*******************************************************************
  136.  
  137. //*******************************************************************
  138. // InitFfind - init the ffind application
  139. //
  140. // paramaters:
  141. //             hInstance     - The instance of this instance of this
  142. //                             application.
  143. //             hPrevInstance - The instance of the previous instance
  144. //                             of this application. This will be 0
  145. //                             if this is the first instance.
  146. //             lpszCmdLine   - A long pointer to the command line that
  147. //                             started this application.
  148. //             cmdShow       - Indicates how the window is to be shown
  149. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  150. //                             SW_MIMIMIZE.
  151. //
  152. //*******************************************************************
  153. #pragma argsused
  154. void InitFfind(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  155.                LPSTR lpszCmdLine, int cmdShow)
  156. {
  157.     if (!hPrevInstance)              // if no previous instance, this is first
  158.         InitFfindFirst(hInstance);
  159.     else
  160.         InitFfindAdded(hPrevInstance);   // this is not first instance
  161.  
  162.     InitFfindEvery(hInstance, cmdShow);  // initialization for all instances
  163.  
  164. }
  165.  
  166. //*******************************************************************
  167. // InitFfindFirst - done only for first instance of ffind
  168. //
  169. // paramaters:
  170. //             hInstance     - The instance of this instance of this
  171. //                             application.
  172. //
  173. //*******************************************************************
  174. void InitFfindFirst(HINSTANCE hInstance)
  175. {
  176.     WNDCLASS wcFfindClass;
  177.  
  178.     // Get string from resource with application name.
  179.     LoadString(hInstance, IDS_NAME, (LPSTR) SetUpData.szAppName, 10);
  180.  
  181.     // Define the window class for this application.
  182.     wcFfindClass.lpszClassName = SetUpData.szAppName;
  183.     wcFfindClass.hInstance     = hInstance;
  184.     wcFfindClass.lpfnWndProc   = FfindWndProc;
  185.     wcFfindClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  186.     wcFfindClass.hIcon         = LoadIcon(hInstance, SetUpData.szAppName);
  187.     wcFfindClass.lpszMenuName  = (LPSTR) NULL;
  188.     wcFfindClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  189.     wcFfindClass.style         = CS_HREDRAW | CS_VREDRAW;
  190.     wcFfindClass.cbClsExtra    = 0;
  191.     wcFfindClass.cbWndExtra    = 0;
  192.  
  193.     // Register the class
  194.     RegisterClass(&wcFfindClass);
  195. }
  196.  
  197. //*******************************************************************
  198. // InitFfindAdded - done only for added instances of ffind
  199. //
  200. // paramaters:
  201. //             hPrevInstance - The instance of the previous instance
  202. //                             of this application.
  203. //
  204. //*******************************************************************
  205. #pragma argsused
  206. void InitFfindAdded(HINSTANCE hPrevInstance)
  207. {
  208.     // get the results of the initialization of first instance
  209.     // GetInstanceData(hPrevInstance, (BYTE*) &SetUpData, sizeof(SETUPDATA));
  210. }
  211.  
  212. //*******************************************************************
  213. // InitFfindEvery - done for every instance of ffind
  214. //
  215. // paramaters:
  216. //             hInstance     - The instance of this instance of this
  217. //                             application.
  218. //             cmdShow       - Indicates how the window is to be shown
  219. //                             initially. ie. SW_SHOWNORMAL, SW_HIDE,
  220. //                             SW_MIMIMIZE.
  221. //
  222. //*******************************************************************
  223. #pragma argsused
  224. void InitFfindEvery(HINSTANCE hInstance, int cmdShow)
  225. {
  226.     TEXTMETRIC tm;
  227.     HDC        hDC;
  228.  
  229.     hInst = hInstance;       // save for use by window procs
  230.  
  231.     // Create applications main window.
  232.     hWndMain = CreateWindow(
  233.                   SetUpData.szAppName,
  234.                   SetUpData.szAppName,
  235.                     WS_BORDER |
  236.                     WS_CAPTION |
  237.                     WS_SYSMENU |
  238.                     WS_MINIMIZEBOX,
  239.                   10,
  240.                   19,
  241.                   256,
  242.                   123,
  243.                   NULL,
  244.                   NULL,
  245.                   hInstance,
  246.                   NULL
  247.                   );
  248.  
  249.     // Get the display context.
  250.     hDC = GetDC(hWndMain);
  251.  
  252.     // Build fixed screen font. Needed to display columinar report.
  253.     cursfont.lfHeight         =  14;
  254.     cursfont.lfWidth          =  9;
  255.     cursfont.lfEscapement     =  0;
  256.     cursfont.lfOrientation    =  0;
  257.     cursfont.lfWeight         =  FW_NORMAL;
  258.     cursfont.lfItalic         =  FALSE;
  259.     cursfont.lfUnderline      =  FALSE;
  260.     cursfont.lfStrikeOut      =  FALSE;
  261.     cursfont.lfCharSet        =  ANSI_CHARSET;
  262.     cursfont.lfOutPrecision   =  OUT_DEFAULT_PRECIS;
  263.     cursfont.lfClipPrecision  =  CLIP_DEFAULT_PRECIS;
  264.     cursfont.lfQuality        =  DEFAULT_QUALITY;
  265.     cursfont.lfPitchAndFamily =  FIXED_PITCH | FF_DONTCARE;
  266.     strcpy((char *)cursfont.lfFaceName, "System");
  267.  
  268.     hnewsfont = CreateFontIndirect( &cursfont);
  269.  
  270.     // Install the font in the current display context.
  271.     holdsfont = SelectObject(hDC, hnewsfont);
  272.  
  273.     // get text metrics for paint
  274.     GetTextMetrics(hDC, &tm);
  275.     xChar = tm.tmAveCharWidth;
  276.     yChar = tm.tmHeight + tm.tmExternalLeading;
  277.     yCharnl = tm.tmHeight;
  278.  
  279.     // Release the display context.
  280.     ReleaseDC(hWndMain, hDC);
  281.  
  282.     // Create a thunk for the main dialog box proc function.
  283.     lpModelessProc = MakeProcInstance((FARPROC)MainDlgBoxProc, hInst);
  284.  
  285.     // Find drive letters for all drives in system.
  286.     // We will only use the hard drives.
  287.     FindDrives(fdrives, hdrives);
  288.     hdrives[9] = 0; // limit drives to max of 9
  289.     ndrives = strlen(hdrives);
  290.  
  291.     InitMainDlg(hWndMain);
  292. }
  293.  
  294. //*******************************************************************
  295. // CloseFfind - done at termination of every instance of ffind
  296. //
  297. //*******************************************************************
  298. void CloseFfind()
  299. {
  300. }
  301.  
  302. //*******************************************************************
  303.  
  304. //*******************************************************************
  305. // FfindWndProc - handles messages for this application
  306. //
  307. // paramaters:
  308. //             hWnd          - The window handle for this message
  309. //             message       - The message number
  310. //             wParam        - The WPARAM parmater for this message
  311. //             lParam        - The LPARAM parmater for this message
  312. //
  313. // returns:
  314. //             depends on message.
  315. //
  316. //*******************************************************************
  317. LRESULT CALLBACK _export FfindWndProc(HWND hWnd, UINT message,
  318.                              WPARAM wParam, LPARAM lParam)
  319. {
  320.     switch (message)
  321.     {
  322.         case WM_MOVE:
  323.             // Move the dialog box on top of our main window every
  324.             // time the main window moves.
  325.             if (IsWindow(hQryDlgBox))
  326.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  327.             break;
  328.  
  329.         case WM_SETFOCUS:
  330.             // Always set the input focus to the dialog box.
  331.             if (IsWindow(hQryDlgBox))
  332.                 SendMessage(hQryDlgBox, message, wParam, lParam);
  333.             break;
  334.  
  335.         case WM_CLOSE:
  336.             // Tell windows to destroy our window.
  337.             DestroyWindow(hWnd);
  338.             break;
  339.  
  340.         case WM_QUERYENDSESSION:
  341.             // If we return TRUE we are saying it's ok with us to end the
  342.                 // windows session.
  343.             return((long) TRUE);  // we agree to end session.
  344.  
  345.         case WM_ENDSESSION:
  346.             // If wParam is not zero, it meany every application said ok
  347.             // to WM_QUERYENDSESSION messages, so we are really ending.
  348.             if (wParam)           // if all apps aggreed to end session.
  349.                 CloseFfind();     // This is the end. We will not get a
  350.                                    // WM_DESTROY message on end session.
  351.             break;
  352.  
  353.         case WM_DESTROY:
  354.             // This is the end if we were closed by a DestroyWindow call.
  355.  
  356.             // Remove font
  357.             DeleteObject(hnewsfont);
  358.  
  359.             CloseFfind();
  360.                 PostQuitMessage(0);
  361.             break;
  362.  
  363.         default:
  364.             return(DefWindowProc(hWnd, message, wParam, lParam));
  365.     }
  366.  
  367.     return(0L);
  368. }
  369.  
  370. //*******************************************************************
  371.  
  372. //*******************************************************************
  373. // InitMainDlg - put up modeless dialog box
  374. //
  375. // paramaters:
  376. //             hWnd          - The window handle of the caller
  377. //
  378. //*******************************************************************
  379. void InitMainDlg(HWND hWnd)
  380. {
  381.     // This structure describes the fixed portion at the begining of a
  382.     // dialog template. The part we are going to modify is dtItemCount
  383.     // to cause the proper number of drive selector boxes to display.
  384.  
  385.     WORD numDrives;
  386.  
  387.     #if !defined(__FLAT__)
  388.  
  389.     // 16 bit dialog template
  390.      typedef struct tagDLGTEMPLATE
  391.     {
  392.         long dtStyle;
  393.         BYTE dtItemCount;
  394.           int  dtX;
  395.         int  dtY;
  396.           int  dtCX;
  397.           int  dtCY;
  398.         char dtResourceName[1];
  399.     }   DLGTEMPLATE;
  400.  
  401.     typedef LPSTR DLGPTR;
  402.  
  403.    #else
  404.  
  405.     // 32 bit dialog template
  406.      typedef struct tagDLGTEMPLATE
  407.      {
  408.         DWORD  dtStyle;
  409.         DWORD  dtExtStyle;
  410.         WORD   dtItemCount;
  411.           SHORT  dtX;
  412.           SHORT  dtY;
  413.           SHORT  dtCX;
  414.           SHORT  dtCY;
  415.      } DLGTEMPLATE;
  416.  
  417.      typedef LPCDLGTEMPLATEA DLGPTR;
  418.  
  419.     #endif
  420.  
  421.      DLGTEMPLATE FAR *dltp, *tempDlgPtr;
  422.  
  423.      LPCSTR resourceStr;
  424.      HRSRC resourceHndl;
  425.  
  426.      // Modifying dialog box parms on the fly.
  427.  
  428.      // Load the dialog box resource.
  429.      resourceStr = MAKEINTRESOURCE(MAIN);
  430.  
  431. //    CreateDialogIndirect(hInst,resourceStr,hWnd,(DLGPROC)lpModelessProc);
  432.  
  433.      resourceHndl = FindResource(hInst, resourceStr, RT_DIALOG);
  434.  
  435.      hdlgr = LoadResource(hInst, resourceHndl);
  436.  
  437.      if (hdlgr)
  438.      {
  439.           // Lock the resource so we have a pointer to it.
  440.           dltp = (DLGTEMPLATE FAR *) LockResource(hdlgr);
  441.           if (dltp)
  442.           {
  443.                 // Change the number of items to display. The drive boxes are
  444.                 // defined last so we can truncate the ones not needed.
  445.  
  446.                 // make a temporary copy of dialog template
  447.                 tempDlgPtr = malloc((size_t)SizeofResource(hInst, resourceHndl));
  448.  
  449. #if defined(__FLAT__)
  450.                 memcpy((void *)tempDlgPtr, (const void *)dltp, (size_t)SizeofResource(hInst, resourceHndl));
  451. #else
  452.                 _fmemcpy((void FAR *)tempDlgPtr, (const void FAR *)dltp, (size_t)SizeofResource(hInst, resourceHndl));
  453. #endif
  454.  
  455.                 numDrives = (WORD)(ndrives + QX_DRV1 - QX_1);
  456.  
  457. #if !defined(__FLAT__)
  458.                 tempDlgPtr->dtItemCount = (BYTE) numDrives;
  459. #else
  460.                 tempDlgPtr->dtItemCount = numDrives;
  461. #endif
  462.                 CreateDialogIndirect(hInst,
  463.                                                   (DLGPTR)tempDlgPtr,
  464.                                                   hWnd,
  465.                                                   (DLGPROC)lpModelessProc);
  466.  
  467.                 // free tempory copy of dialog template
  468.  
  469.                 free(tempDlgPtr);
  470.  
  471.  
  472.                 // Unlock dialog resource we locked above.
  473.  
  474. #if !defined(__FLAT__)
  475.                 UnlockResource(hdlgr);
  476. #endif
  477.  
  478.                 // Free it.
  479.                 FreeResource(hdlgr);
  480.  
  481.                 // Zero handle to it.
  482.                 hdlgr = 0;
  483.           }
  484.      }
  485.  
  486. }
  487.  
  488. //*******************************************************************
  489. // MainDlgBoxProc - handle Main dialog messages (modeless)
  490. //
  491. // This is a modeless dialog box procedure that controls this
  492. // entire application.
  493. //
  494. // paramaters:
  495. //             hDlg          - The window handle for this message
  496. //             message       - The message number
  497. //             wParam        - The WPARAM parameter for this message
  498. //             lParam        - The LPARAM parameter for this message
  499. //
  500. //*******************************************************************
  501. #pragma argsused
  502. BOOL CALLBACK _export MainDlgBoxProc(HWND hDlg, UINT message,
  503.                            WPARAM wParam, LPARAM lParam)
  504. {
  505.     static HWND   hlistwnd;
  506.     static RECT   wrect;
  507.  
  508.     int           x, y, w, h, i;
  509.     long          rc;
  510.     char         *cp, *cpd, tmp[30], sdrives[30];
  511.     HANDLE        hCursor;
  512.  
  513.     switch (message)
  514.     {
  515.         case WM_INITDIALOG:
  516.             // Save the handle of this proc for use by main window proc.
  517.             hQryDlgBox = hDlg;
  518.  
  519.             // Set names of drives in drive box text.
  520.             cp = hdrives;
  521.             for (i = 0; i < ndrives; i++)
  522.             {
  523.                 sprintf(tmp, "%c:", *cp++);
  524.                 SetDlgItemText(hDlg, QX_DRV1 + i, tmp);
  525.             }
  526.  
  527.             // Select the first drive.
  528.             SendMessage(GetDlgItem(hDlg, QX_DRV1), BM_SETCHECK, TRUE, 0L);
  529.  
  530.             // Get position of dialog box window.
  531.             GetWindowRect(hDlg, (LPRECT) &wrect);
  532.             w = wrect.right - wrect.left;
  533.             h = wrect.bottom - wrect.top;
  534.  
  535.             // Move main application window to same position.
  536.             SetWindowPos(hWndMain, hDlg,
  537.                          wrect.left, wrect.top, w, h,
  538.                          0);
  539.  
  540.             // Establish initial value of file name pattern box.
  541.             strcpy(file_name_pattern, "*.cpp");
  542.             SetDlgItemText(hDlg, QX_PATTERN, file_name_pattern);
  543.             SetFocus(GetDlgItem(hDlg, QX_PATTERN));
  544.  
  545.             // Save handle of list box control because we use it a lot.
  546.             hlistwnd = GetDlgItem(hDlg, QX_LIST);
  547.  
  548.             // Install fixed fonts for those controls that need it.
  549.             SendMessage(GetDlgItem(hDlg, QX_3), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  550.             SendMessage(GetDlgItem(hDlg, QX_4), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  551.             SendMessage(GetDlgItem(hDlg, QX_5), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  552.             SendMessage(GetDlgItem(hDlg, QX_6), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  553.             SendMessage(GetDlgItem(hDlg, QX_7), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  554.             SendMessage(GetDlgItem(hDlg, QX_LIST), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  555.             SendMessage(GetDlgItem(hDlg, QX_COUNT), WM_SETFONT, (WPARAM)hnewsfont, FALSE);
  556.             break;
  557.  
  558.         case WM_MOVE:
  559.             // Always keep this dialog box on top of main window.
  560.             GetWindowRect(hWndMain, (LPRECT) &wrect);
  561.             x = wrect.left;
  562.             y = wrect.top;
  563.             w = wrect.right - wrect.left;
  564.             h = wrect.bottom - wrect.top;
  565.             MoveWindow(hDlg, x, y, w, h, 1);
  566.             break;
  567.  
  568.         case WM_SYSCOMMAND:
  569.             // Pass WM_SYSCOMMAND messages on to main window so both
  570.             // main window and dialog box get iconized, minimized etc.
  571.             // in parallel.
  572.             SendMessage(hWndMain, message, wParam, lParam);
  573.             break;
  574.  
  575.         case WM_COMMAND:
  576.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  577.             {
  578.                 case QX_PATTERN:                 // Pattern string
  579.                     GetDlgItemText(hDlg, GET_WM_COMMAND_ID(wParam, lParam),
  580.                                    qrtxt, MAX_QRT_LEN);
  581.                     break;
  582.  
  583.                 case QX_SEARCH:                  // File button
  584.                     strcpy(file_name_pattern, qrtxt);
  585.  
  586.                     // Build list of selected drives.
  587.                     cp = hdrives;
  588.                     cpd = sdrives;
  589.                     for ( i = 0; i < ndrives; i++)
  590.                     {
  591.                         if (SendMessage(GetDlgItem(hDlg, QX_DRV1 + i), BM_GETCHECK, 0, 0L))
  592.                             *cpd++ = *cp;
  593.                         cp++;
  594.                     }
  595.                     *cpd = 0;
  596.  
  597.                     // Clear any previous list and count.
  598.                     SendMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(QX_CLEARW, 0, 0));
  599.  
  600.                     // Tell list control not to display till we are done
  601.                     SendDlgItemMessage(hDlg, QX_LIST, WM_SETREDRAW, FALSE, 0L);
  602.  
  603.                     // Load hour-glass cursor.
  604.                     hCursor = LoadCursor(NULL, IDC_WAIT);
  605.                     SetCursor(hCursor);
  606.  
  607.                     // Go find files matching pattern on selected drives.
  608.                     rc = FindFile(sdrives, file_name_pattern);
  609.  
  610.                     // Tell list control ok to redraw itself.
  611.                     SendDlgItemMessage(hDlg, QX_LIST, WM_SETREDRAW, TRUE, 0L);
  612.  
  613.                     // Reload arrow cursor.
  614.                     SetCursor(hCursor);
  615.  
  616.                     // See if out of memory error.
  617.                     if (rc < 0)
  618.                     {
  619.                         MessageBox(hDlg,
  620.                                    "Out of memory",
  621.                                    "--ERROR--",
  622.                                    MB_APPLMODAL | MB_ICONEXCLAMATION | MB_OK);
  623.                     }
  624.  
  625.                     // Show count of files fount.
  626.                     sprintf(tmp, "# %5ld", file_count);
  627.                     SetDlgItemText(hDlg, QX_COUNT, tmp);
  628.  
  629.                     // Show list window.
  630.                     InvalidateRect(hlistwnd, NULL, TRUE);
  631.                     UpdateWindow(hlistwnd);
  632.                     break;
  633.  
  634.                 case QX_CLEARW:
  635.                     // Clear list window.
  636.                     SendMessage(hlistwnd, LB_RESETCONTENT, 0L, 0L);
  637.                                         InvalidateRect(hlistwnd, NULL, TRUE);
  638.                     UpdateWindow(hlistwnd);
  639.  
  640.                     // Set count to 0.
  641.                     file_count = 0;
  642.                     sprintf(tmp, "# %5ld", file_count);
  643.                     SetDlgItemText(hDlg, QX_COUNT, tmp);
  644.                     break;
  645.  
  646.                 case QX_CANCEL:                  // Cancel button
  647.                     // Tell main application window we want to quit.
  648.                     SendMessage(hWndMain, WM_CLOSE, 0, 0L);
  649.                     break;
  650.  
  651.                 default:
  652.                     break;
  653.             }
  654.             break;
  655.  
  656.         case WM_CLOSE:
  657.             // Unlock dialog resource we locked above.
  658.  
  659.             #if !defined(__FLAT__)
  660.             UnlockResource(hdlgr);
  661.             #endif
  662.  
  663.             // Free it.
  664.             FreeResource(hdlgr);
  665.  
  666.             // Zero handle to it.
  667.             hdlgr = 0;
  668.  
  669.             // Zero handle to this dialog window.
  670.             hQryDlgBox = 0;
  671.  
  672.             // Tell main window to close.
  673.             PostMessage(hWndMain, WM_CLOSE, 0, 0L);
  674.  
  675.             // Destroy ourseleves.
  676.             DestroyWindow(hDlg);
  677.             break;
  678.  
  679.         default:
  680.             return FALSE;
  681.     }
  682.  
  683.     return(TRUE);
  684. }
  685.  
  686. //*******************************************************************
  687.  
  688. //*******************************************************************
  689. // FindFile - find files matching a pattern files on specified drives
  690. //
  691. // paramaters:
  692. //             drives   - An array of drive letters to search.
  693. //             pattern  - A file name pattern.
  694. //
  695. // returns:
  696. //             Number of files found matching pattern.
  697. //             If unable to add a name to listbox, number is returned as
  698. //             a negative.
  699. //
  700. //*******************************************************************
  701. long FindFile(char *drives, char *pattern)
  702. {
  703.     char     tree[3];
  704.     int      nfiles;
  705.     long      rc;
  706.  
  707.     rc = 0;
  708.     file_count = 0;
  709.     tree[1] = ':';
  710.     tree[2] = 0;
  711.     while (*drives)
  712.     {
  713.         tree[0] = *drives++;
  714.         nfiles = DoADir(tree, "*.*", pattern);
  715.         if (nfiles >= 0)
  716.             file_count += nfiles;
  717.         else
  718.         {
  719.             file_count -= nfiles;
  720.             rc = -file_count;
  721.             break;
  722.         }
  723.     }
  724.  
  725.     return(rc);
  726. }
  727.  
  728. //*******************************************************************
  729. // DoADir - search a directory for files matching a file name pattern
  730. //          recursivly search sub directories
  731. //
  732. // paramaters:
  733. //             patternp  - A path to search.
  734. //             patternn  - A file name pattern to use to find directories.
  735. //             include   - A file name pattern to use to select files.
  736. //
  737. // returns:
  738. //             Number of files found matching include.
  739. //             If unable to add a name to listbox, number is returned as
  740. //             a negative.
  741. //
  742. //*******************************************************************
  743. int DoADir(char *patternp, char *patternn, char *include)
  744. {
  745.     char          patternw[MAX_PATH];
  746.     char          npatternp[MAX_PATH];
  747.     char          buf[256];
  748.     int           mfiles;
  749.     int           have_subs;
  750.     int           nfiles;
  751.     LONG          lrc;
  752.     struct ffblk  fileinfo;
  753.  
  754.     strcpy(patternw, patternp);
  755.     strcat(patternw, "\\");
  756.  
  757.     strcat(patternw, patternn);
  758.  
  759.     mfiles = 0;
  760.     have_subs = 0;
  761.  
  762.     if (!findfirst(patternw, &fileinfo, FA_DIREC))
  763.     {
  764.         do
  765.         {
  766.             if (fileinfo.ff_attrib & FA_DIREC)  // subdirectory
  767.             {
  768.                 if (fileinfo.ff_name[0] != '.')  // ignore . and ..
  769.                     have_subs = 1;
  770.             }
  771.             else                              // file
  772.             {
  773.                 if (FnMatch(include, fileinfo.ff_name))
  774.                 {
  775.                     mfiles++;
  776.  
  777.                     FmtEntry(buf, fileinfo.ff_name, patternp,
  778.                              fileinfo.ff_ftime, fileinfo.ff_fdate, fileinfo.ff_fsize);
  779.  
  780.                     lrc = SendDlgItemMessage(hQryDlgBox, QX_LIST, LB_ADDSTRING, 0,
  781.                                             (LONG) ((LPSTR) buf));
  782.  
  783.                     if (lrc == LB_ERR || lrc == LB_ERRSPACE)
  784.                         return(-mfiles); // error return
  785.                 }
  786.             }
  787.         }
  788.         while (!findnext(&fileinfo));
  789.     }
  790.  
  791.     if (have_subs)
  792.     {
  793.         if (!findfirst(patternw, &fileinfo, FA_DIREC))
  794.         {
  795.             do
  796.             {
  797.                 if (fileinfo.ff_attrib & FA_DIREC)  // subdirectory
  798.                 {
  799.                     if (fileinfo.ff_name[0] != '.')  // ignore . and ..
  800.                     {
  801.                         strcpy(npatternp, patternp);
  802.                         strcat(npatternp, "\\");
  803.                         strcat(npatternp, fileinfo.ff_name);
  804.  
  805.                         nfiles = DoADir(npatternp, patternn, include);
  806.  
  807.                         if (nfiles >= 0)
  808.                             mfiles += nfiles;
  809.                         else
  810.                         {
  811.                                                         mfiles -= nfiles;
  812.                             return(-mfiles); // error return
  813.                         }
  814.                     }
  815.                 }
  816.             }
  817.             while (!findnext(&fileinfo));
  818.         }
  819.         }
  820.  
  821.         return(mfiles);
  822. }
  823.  
  824. //*******************************************************************
  825. // FindDrives - find floppy and hard drives in system
  826. //
  827. // paramaters:
  828. //             fdrives - An array to hold floppy drive letters.
  829. //             hdrives - An array to hold hard drive letters.
  830. //
  831. //*******************************************************************
  832. void FindDrives(char *fdrives, char *hdrives)
  833. {
  834.         unsigned int  savedriveno;
  835.           unsigned int  maxdriveno;
  836.           unsigned int  driveno;
  837.           unsigned int  drivetype;
  838.           int           nfdrives = 0;
  839.           int           nhdrives = 0;
  840. #ifdef __FLAT__
  841.           char driveroot[4];
  842. #endif
  843.  
  844.           savedriveno = getdisk() + 1;               // save current drive
  845.           maxdriveno = setdisk(savedriveno - 1);     // find max drive in system
  846.  
  847.  
  848.           for (driveno=0; driveno<maxdriveno; driveno++)
  849.                      {
  850. #ifdef __FLAT__
  851.                      strcpy(driveroot, " :\\");
  852.                      driveroot[0] = (char)('A'+driveno);
  853.                      drivetype = GetDriveType(driveroot);
  854. #else
  855.                      drivetype = GetDriveType(driveno);
  856. #endif
  857.                      if (drivetype == 0)
  858.                                 continue;
  859.                      else
  860.                                 if (drivetype == DRIVE_REMOVABLE)
  861.                                 {
  862.                         fdrives[nfdrives++] = (char) (driveno + 'A');
  863.                         }
  864.                         else
  865.                                 {
  866.                                 hdrives[nhdrives++] = (char) (driveno + 'A');
  867.                                 }
  868.                 }
  869.  
  870.         fdrives[nfdrives] = 0;
  871.         hdrives[nhdrives] = 0;
  872.  
  873.           setdisk(savedriveno - 1);                  // reset current drive
  874. }
  875.  
  876. //*******************************************************************
  877.  
  878. //*******************************************************************
  879. // FnMatch - test if a file name matches a file name pattern.
  880. //           handles * and ? wildcard characters.
  881. //
  882. // paramaters:
  883. //             pat   - A file name pattern (ie. xyz?.*)
  884. //             name  - A file name to test against pat (ie. xyz1.c)
  885. //
  886. // returns:
  887. //             1 - if match
  888. //             0 - if not a match
  889. //
  890. //*******************************************************************
  891. FnMatch(char *pat, char *name)
  892. {
  893.     int   match;
  894.     int   ndone;
  895.     char *cpp;
  896.     char *cpn;
  897.  
  898.     cpp = pat;
  899.     cpn = name;
  900.     match = 1;
  901.     ndone = 1;
  902.     while (ndone)
  903.     {
  904.         switch (*cpp)
  905.         {
  906.             case '*':
  907.                 // skip to next letter
  908.                 cpp++;
  909.  
  910.                 // skip to next letter
  911.                 cpn = strchr(cpn, *cpp);
  912.                 if (cpn == NULL)
  913.                 {
  914.                     cpn = name;
  915.                     while (*cpn)
  916.                          cpn++;
  917.                 }
  918.                 break;
  919.  
  920.             case '?':
  921.                 cpp++;
  922.                 cpn++;
  923.                 break;
  924.  
  925.             case 0:
  926.                 if (*cpn != 0)
  927.                     match = 0;
  928.                 ndone = 0;
  929.                 break;
  930.  
  931.             default:
  932.                 if (tolower(*cpp) == tolower(*cpn))
  933.                 {
  934.                     cpp++;
  935.                     cpn++;
  936.                 }
  937.                 else
  938.                 {
  939.                     match = 0;
  940.                     ndone = 0;
  941.                 }
  942.                 break;
  943.         }
  944.     }
  945.  
  946.     return(match);
  947. }
  948.  
  949. //*******************************************************************
  950. // FmtEntry - format directory entry for report
  951. //
  952. // paramaters:
  953. //             buf      - A buffer to hold formated directory entry.
  954. //             name     - File name.
  955. //             patternp - Path on which file was found.
  956. //             time     - File time from directory.
  957. //             date     - File data from directory.
  958. //             szie     - File size from directory.
  959. //
  960. // returns:
  961. //             A pointer to buf.
  962. //
  963. //*******************************************************************
  964. char *FmtEntry(char *buf, char *name, char *patternp,
  965.                unsigned time, unsigned date, long size)
  966. {
  967.     char   *cp;
  968.     char    xname[256];
  969.     char    xext[256];
  970.     int     mo, dd, yy, hh, mi, ss;
  971.  
  972.     cp = strrchr(name, '.');
  973.  
  974.     if (cp)
  975.     {
  976.         *cp = 0;
  977.         strcpy(xname, name);
  978.         strcpy(xext, cp + 1);
  979.     }
  980.     else
  981.     {
  982.         strcpy(xname, name);
  983.         strcpy(xext, "");
  984.     }
  985.  
  986.     // Truncate extremely long filenames
  987.     if (strlen(xname) > 16)
  988.         strcpy(xname+13, "...");
  989.  
  990.  
  991.     mo = (date >> 5) & 0x0f;
  992.     dd = date & 0x1f;
  993.     yy = ((date >> 9) & 0x7f) + 80;
  994.     hh = (time >> 11) & 0x1f;
  995.     mi = (time >> 5) & 0x3f;
  996.     ss = (time & 0x1f) * 2;
  997.  
  998.     sprintf(buf, "%-20s.%-3s %7ld %02d/%02d/%02d %02d:%02d:%02d %s",
  999.                   xname,
  1000.                   xext,
  1001.                   size,
  1002.                   mo, dd, yy,
  1003.                   hh, mi, ss,
  1004.                   patternp);
  1005.  
  1006.     return(buf);
  1007. }
  1008.  
  1009. //*******************************************************************
  1010.  
  1011.  
  1012.